package com.abo.yaas.i18n;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import com.vaadin.Application;
import com.vaadin.service.ApplicationContext.TransactionListener;

/**
 * A utility class for keeping track of the used locale instance for each
 * application
 */
@SuppressWarnings("serial")
public class Lang implements TransactionListener {
    
    public static void addListener(final LocaleChangeListener listener) {
        if (instance.get().listeners == null) {
            instance.get().listeners = new ArrayList<LocaleChangeListener>();
        }
        instance.get().listeners.add(listener);
    }

    private static void fireLocaleChangedEvent() {
        if (instance.get().listeners == null) {
            return;
        }
        final LocaleChangedEvent event = new LocaleChangedEvent(
                instance.get().locale);
        for (final LocaleChangeListener listener : instance.get().listeners) {
            listener.localeChanged(event);
        }
    }

    /**
     * Get the translated message for the locale set in Lang
     * 
     * @param identifier
     *            Key for the translation message
     * @param params
     *            Parameters for the translation message
     * @return Translated message string
     */
    public static String getMessage(String identifier, Object... params) {
        return InternationalizationServlet.getMessage(
                getLocale().getLanguage(), identifier, params);
    }

    /**
     * Initializes the {@link Lang} for the given {@link Application}
     * 
     * @param application
     */
    public static void initialize(Application application) {
        if (application == null) {
            throw new IllegalArgumentException("Application may not be null");
        }
        final Lang handler = new Lang(application);
        application.getContext().addTransactionListener(handler);
    }

    /**
     * Listeners that should perform some logic if the locale is changed
     */
    private List<LocaleChangeListener> listeners;

    private Locale locale = Locale.getDefault();

    private static ThreadLocal<Lang> instance = new ThreadLocal<Lang>();

    /**
     * Get the current locale for the application
     * 
     * @return Locale
     */
    public static Locale getLocale() {
        return instance.get().locale;
    }

    /**
     * Set the current locale for the application
     * 
     * @param locale
     *            Locale
     */
    public static void setLocale(Locale locale) {
        instance.get().locale = locale;
        fireLocaleChangedEvent();
    }

    private final Application application;

    /**
     * Constructor. Takes as parameter the application instance.
     * 
     * @param application
     *            Application instance.
     */
    public Lang(Application application) {
        this.application = application;
        instance.set(this);
    }

    public static void removeListener(final LocaleChangeListener listener) {
        if (instance.get().listeners == null) {
            return;
        }
        instance.get().listeners.remove(listener);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void transactionEnd(Application application, Object transactionData) {
        if (this.application == application) {
            instance.set(null);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void transactionStart(Application application, Object transactionData) {
        if (this.application == application) {
            instance.set(this);
        }
    }

}
